package front

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/google/uuid"
	"github.com/gorilla/websocket"
)

// 中枢
type hub struct {
	C             map[*connection]bool     // 连接状态Map
	OnlineMsgPool chan Message             // 广播消息池(在线)
	R             chan *connection         // 连接池
	U             chan *connection         // 离线池
	UserClientM   map[string][]*connection // 客户端ID
}

func (h *hub) Run() {
	for {
		select {
		// 监听用户连接池
		case c := <-h.R:
			h.C[c] = true
			c.Data.Ip = c.ws.RemoteAddr().String()
			c.Data.ID = strings.ReplaceAll(uuid.New().String(), "-", "")
			c.Data.Status = 1
			// 回复用户
			_ = c.ws.WriteMessage(
				websocket.TextMessage,
				func() (res []byte) {
					res, _ = json.Marshal(Message{SourceType: "system", Type: "connect", PrivateToID: c.Data.UserId, Data: "连接成功"})
					return
				}(),
			)
			// 发送公共通知
			go func() {
				h.OnlineMsgPool <- Message{SourceType: "system", Type: "public", DataType: "msg", Data: fmt.Sprintf("%s: 上线了", c.Data.UserInfo.Name)}
			}()

			// 更新关系Map
			if v, ok := h.UserClientM[c.Data.UserId]; ok {
				h.UserClientM[c.Data.UserId] = append(v, c)
			} else {
				h.UserClientM[c.Data.UserId] = []*connection{c}
			}

		// 监听用户状态池，更新状态
		case c := <-h.U:
			// 判断用户是否在连接池
			if _, ok := h.C[c]; ok {
				// 下线通知
				go func() {
					h.OnlineMsgPool <- Message{SourceType: "system", Type: "public", Data: fmt.Sprintf("%s: 下线了", c.Data.UserInfo.Name)}
				}()
				delete(h.C, c)

				var userClientMV []*connection
				userClientMV_ := h.UserClientM[c.Data.UserId]

				for _, v := range userClientMV_ {
					if v != c {
						userClientMV = append(userClientMV, v)
					}
				}
				h.UserClientM[c.Data.UserId] = userClientMV
				fmt.Printf("删除后的用户数:%d\n", len(h.C))
				close(c.Sc)
			}

		// 监听在线消息池，集中处理
		case dataB := <-h.OnlineMsgPool:
			switch dataB.Type {
			case "public":
				// 发送给所有用户
				for c := range h.C {
					c := c
					go func() {
						defer func() {
							if err := recover(); err != nil {
								fmt.Printf("revover: %v\n", err)
							}
						}()
						c.Sc <- dataB
					}()
				}
			case "private":
				go func() {
					if cs, ok := h.UserClientM[dataB.PrivateToID]; ok {
						// 发送给该用户所有设备
						for _, c := range cs {
							fmt.Printf("在线用户数：%d\n", len(cs))
							go func() {
								defer func() {
									if err := recover(); err != nil {
										fmt.Printf("revover: %v\n", err)
									}
								}()
								c.Sc <- dataB
							}()
						}
					} else {
						// 用户未在线
						// h.UserClientM[dataB.FromID].Sc <- Message{
						// 	SourceType:      "system",
						// 	Type:        "private",
						// 	PrivateToID: dataB.FromID,
						// 	DataType:    "msg",
						// 	Data:        "该用户未在线",
						// }
					}
				}()
			}

		}
	}
}

var HUB = hub{
	C:             make(map[*connection]bool),
	U:             make(chan *connection),
	OnlineMsgPool: make(chan Message),
	R:             make(chan *connection),
	UserClientM:   make(map[string][]*connection),
}

type Message struct {
	FromID      string `json:"from_id"`     // 来源客户端ID
	PrivateToID string `json:"private_id"`  // 私信客户端ID
	GroupID     string `json:"group_id"`    // 群组ID
	Type        string `json:"type"`        // 消息类型：connect:连接、public:公开、group:群组、private:私信、report:上报
	DataType    string `json:"data_type"`   // 消息内容类型（msg）
	SourceType  string `json:"source_type"` // 消息来源：system:系统、client:客户端、bot:机器人
	Data        string `json:"data"`        // 消息内容
	Time        string `json:"time"`        // 时间
}
